home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 051-075 / disk_059 / browser / menustack.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  7KB  |  233 lines

  1. /*
  2.  *  Simple menu package.  Needs lotsa work to handle some cases.
  3.  *
  4.  *  Copyright 1985
  5.  *  Louis A. Mamakos
  6.  *  Software & Stuff
  7.  *  14813 Ashford Place
  8.  *  Laurel, MD  20707
  9.  *
  10.  *  For non-commerical use only.  This program, or any modifications, may not
  11.  *  be sold or incorporated into any product without prior permission from the
  12.  *  author.
  13.  *
  14.  *  Modified by mwm to handle "stacking" menus.
  15.  *   NB - adding item to a menu that's been "popped" back to doesn't work,
  16.  *   and probably never will.
  17.  *    I took at the subitem code at the same time - mwm
  18.  */
  19.  
  20. /* Change if your terminal isn't * x 400 */
  21. #define SCREENHEIGHT      200
  22.  
  23. #include <exec/types.h>
  24. #include <exec/nodes.h>
  25. #include <exec/lists.h>
  26. #include <exec/ports.h>
  27. #include <exec/devices.h>
  28. #include <exec/memory.h>
  29. #include <hardware/blit.h>
  30. #include <graphics/copper.h>
  31. #include <graphics/regions.h>
  32. #include <graphics/rastport.h>
  33. #include <graphics/gfxbase.h>
  34. #include <graphics/gels.h>
  35. #include <intuition/intuition.h>
  36.  
  37. #define MNUM(menu,item,sub) (SHIFTMENU(menu)|SHIFTITEM(item)|SHIFTSUB(sub))
  38.  
  39. struct   Mem_Node {
  40.    struct Node mn_Node;
  41.    struct Remember mn_Memory;
  42.    struct Menu *mn_Menu;
  43.    } *Top, *RemHead();
  44.  
  45. static struct List Memory;
  46. static int Cur_Menu, Cur_MenuItem, Cur_SubItem;
  47. static struct Menu *LastMenu;
  48. static struct MenuItem *LastMenuItem;
  49.  
  50. struct Menu *AutoMenu;      /* menu struct being dynamically built */
  51.  
  52. char *strsave();       /* Save a string in the remember list */
  53.  
  54. Menu_Init()
  55. {
  56.    Memory.lh_Head = (struct Node *) &(Memory.lh_Tail);
  57.    Memory.lh_TailPred = (struct Node *) &(Memory.lh_Head);
  58.    Memory.lh_Tail = NULL;
  59.    Memory.lh_Type = NT_MEMORY;
  60.    Top = NULL;
  61.    Cur_Menu = Cur_MenuItem = -1;
  62.    AutoMenu = LastMenu = NULL;     /* no menu chain yet */
  63.    LastMenuItem = NULL;
  64. }
  65.  
  66. Menu_Clear()
  67. {
  68.  
  69.    while ((Top = RemHead(&Memory)) != NULL) {
  70.       FreeRemember(&(Top->mn_Memory), TRUE);
  71.       FreeMem(Top, sizeof(struct Mem_Node));
  72.   }
  73.   Menu_Init();         /* Just for safeties sake */
  74. }
  75.  
  76. Menu_Pop()
  77. {
  78.  
  79.    if ((Top = RemHead(&Memory)) == NULL) return NULL;
  80.    FreeRemember(&(Top->mn_Memory), FALSE);
  81.    FreeMem(Top, sizeof(struct Mem_Node));
  82.    /* Now, set Top back to the real list head */
  83.    Top = (struct Mem_Node *) Memory.lh_Head;
  84.    LastMenu = Top->mn_Menu;
  85.    LastMenu->NextMenu->Flags = MIDRAWN;
  86.    LastMenuItem = NULL;
  87.    Cur_Menu--;
  88. }
  89. /*
  90.  *  Add a MENU item.  Args are the text of the menu item, and an enable
  91.  *  flag.  Returns an Intuition type menu number, with the MenuItem and
  92.  *  Menu SubItem being NOITEM and NOSUB.  The MENUITEM part is valid.
  93.  */
  94. Menu_Add(name, enabled)
  95.    char *name;
  96.    int enabled;
  97. {
  98.    register struct Menu *m;
  99.  
  100.    if ((Top = (struct Mem_Node *) AllocMem(
  101.        sizeof(struct Mem_Node), MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  102.       return NULL;
  103.    Top->mn_Node.ln_Type = NT_MEMORY;
  104.  
  105.    if ((m = (struct Menu *)AllocRemember(&(Top->mn_Memory),
  106.                  sizeof (struct Menu), MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  107.       return NULL;
  108.    Top->mn_Menu = m;
  109.  
  110.    if (LastMenu == NULL)
  111.       AutoMenu = m;     /* first menu on list */
  112.    else
  113.       LastMenu->NextMenu = m;      /* link it in */
  114.  
  115.    LastMenuItem = NULL;            /* end of previous MenuItem list */
  116.    Cur_MenuItem = -1; /* reset item numbers */
  117.    if (LastMenu == NULL)
  118.       m->LeftEdge = 0;
  119.    else
  120.       m->LeftEdge = LastMenu->LeftEdge + LastMenu->Width;
  121.    m->TopEdge = 0;
  122.    m->Width = strlen(name) * 8;
  123.    Top->mn_Node.ln_Name = m->MenuName = strsave(name);
  124.    m->Height = 0;
  125.    m->Flags = enabled ? MENUENABLED : 0;
  126.    m->FirstItem = NULL;
  127.    LastMenu = m;
  128.  
  129.    AddHead(&Memory, Top);
  130.    return MNUM(++Cur_Menu, NOITEM, NOSUB);
  131. }
  132.  
  133. /*
  134.  *  Add a menu item to the current MENU.  Note that Add_Menu *must* be
  135.  *  called before this function.
  136.  */
  137. Menu_Item_Add(name, flags, mux, ch)
  138.    char *name;       /* name of menu item */
  139.    USHORT flags;
  140.    LONG mux;         /* mutual exclusion mask */
  141.    BYTE ch;        /* command sequence character, if COMMSEQ */
  142. {
  143.    register struct MenuItem *m, *n;
  144.    register struct IntuiText *it;
  145.  
  146.    flags &= CHECKIT|CHECKED|COMMSEQ|MENUTOGGLE|ITEMENABLED|HIGHCOMP|HIGHBOX;
  147.    if (LastMenu == NULL)
  148.       return MNUM(NOMENU, NOITEM, NOSUB);
  149.  
  150.    if ((m = (struct MenuItem *) AllocRemember(&(Top->mn_Memory),
  151.                  sizeof(struct MenuItem), MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  152.       return MNUM(NOMENU, NOITEM, NOSUB);
  153.  
  154.    if (LastMenuItem == NULL)
  155.       LastMenu->FirstItem  = m;
  156.    else
  157.       LastMenuItem->NextItem = m;
  158.    m->Flags = flags | ITEMTEXT;
  159.    /*
  160.     *  Check for highlight mode:  if none selected, use HIGHCOMP
  161.     */
  162.    if ((m->Flags & (HIGHCOMP | HIGHBOX)) == 0)
  163.       m->Flags |= HIGHCOMP;
  164.    m->Command = ch;
  165.    m->MutualExclude = mux;
  166.    m->SubItem = NULL;
  167.    m->ItemFill = (APTR) AllocRemember(&(Top->mn_Memory),
  168.                       sizeof(struct IntuiText), MEMF_PUBLIC | MEMF_CLEAR);
  169.    it = (struct IntuiText *) m->ItemFill;
  170.    it->FrontPen = AUTOFRONTPEN;
  171.    it->BackPen = AUTOBACKPEN;
  172.    it->DrawMode = JAM2;
  173.    if (flags & CHECKIT)
  174.       it->LeftEdge = CHECKWIDTH + 1;
  175.    else
  176.       it->LeftEdge = 1;
  177.    it->TopEdge = 1;
  178.    it->ITextFont = NULL;      /* default font */
  179.    it->IText = strsave(name);
  180.    it->NextText = NULL;
  181.    m->Width = 0;
  182.    if (LastMenuItem == NULL) {
  183.       m->TopEdge = 2;
  184.       m->LeftEdge = 0;
  185.    } else if (LastMenuItem->TopEdge + 40 > SCREENHEIGHT) {
  186.       m->TopEdge = 2;
  187.       m->LeftEdge = LastMenuItem->LeftEdge + LastMenuItem->Width + 12;
  188.    } else {
  189.       m->TopEdge = LastMenuItem->TopEdge + 12;
  190.       m->LeftEdge = LastMenuItem->LeftEdge;
  191.    }
  192.    if (flags & CHECKIT)
  193.       m->Width += CHECKWIDTH;
  194.    if (flags & COMMSEQ)
  195.       m->Width += COMMWIDTH + 20;
  196.    m->Width += IntuiTextLength(m->ItemFill);
  197.    m->Height = 10;
  198.    /*
  199.     *  Check last menu item's width to see if it is larger than this
  200.     *  item's.  If new item is larger, then update width of all other
  201.     *  items.
  202.     */
  203.    if (LastMenuItem) {
  204.       if (LastMenuItem->Width > m->Width)
  205.         m->Width = LastMenuItem->Width;
  206.       else {
  207.          register short delta = m->Width - LastMenuItem->Width;
  208.  
  209.     for (n = LastMenu->FirstItem; n != m; n = n->NextItem) {
  210.        n->Width = m->Width;
  211.        n->NextSelect = MENUNULL;
  212.        if (n->LeftEdge > 0) n->LeftEdge += delta;
  213.     }
  214.     if (m->LeftEdge > 0) m->LeftEdge += delta;
  215.       }
  216.    }
  217.    LastMenuItem = m;
  218.    return MNUM(Cur_Menu, ++Cur_MenuItem, NOSUB);
  219. }
  220.  
  221.  
  222.  
  223. char *
  224. strsave(string) char *string; {
  225.    char *out ;
  226.  
  227.    out = (char *) AllocRemember(&(Top->mn_Memory), strlen(string) + 1,
  228.    MEMF_PUBLIC) ;
  229.    if (out == NULL) return NULL ;
  230.    (void) strcpy(out, string) ;
  231.    return out ;
  232. }
  233.